﻿#include <QDebug>
#include <QVector>
#include <QDateTime>
#include <algorithm>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>
#include <QJsonParseError>
#include "TrDataManager.h"
#include <spdlog/spdlog.h>

TrDataManager::TrDataManager(const QString& code, WTSKlinePeriod period) :
    m_KlinePeriod(period),
    m_strCode(code)
{
    memset(&m_newBar, 0, sizeof(m_newBar));
}

void TrDataManager::OnTick(CThostFtdcDepthMarketDataField* tick)
{
    if(QString(tick->InstrumentID) != m_strCode) return;

    m_dLastPrice = tick->LastPrice;

    if(QString(tick->TradingDay).length() != 8)
        strcpy_s(tick->TradingDay, sizeof (tick->TradingDay), QDate::currentDate().toString("yyyyMMdd").toStdString().c_str());

    m_uLastUpdate = QDateTime::fromString(QString(tick->TradingDay).append(" ").append(QString(tick->UpdateTime)), "yyyyMMdd hh:mm:ss").toTime_t();

    uint    t = 60;
    switch (m_KlinePeriod) {
    case KP_Minute5:
        t = t * 5;
        break;
    case KP_Minute15:
        t = t * 15;
        break;
    case KP_Minute60:
        t = t * 60;
        break;
    default:
        t = t * 60 * 128400;
        break;
    }

    //qDebug() << QString(tick->TradingDay).append(" ").append(QString(tick->UpdateTime));

//    if(m_uLastUpdate < m_vecBars.back().date + t)
//    {
//        m_newBar.date   =   m_uLastUpdate;
//        m_newBar.time   =   m_uLastUpdate;
//        m_newBar.close  =   m_dLastPrice;
//        m_newBar.vol    =   m_newBar.vol + tick->Volume;
//        if(static_cast<uint>(m_newBar.open) == 0)
//        {
//            m_newBar.open = m_dLastPrice;
//        }
//        if(m_newBar.high < m_dLastPrice)
//        {
//            m_newBar.high = m_dLastPrice;
//        }
//        if(m_newBar.low > m_dLastPrice)
//        {
//            m_newBar.low = m_dLastPrice;
//        }
//    } else {
//        m_vecOpen.push_back(m_newBar.open);
//        m_vecHigh.push_back(m_newBar.high);
//        m_vecLow.push_back(m_newBar.low);
//        m_vecClose.push_back(m_newBar.close);
//        m_vecVolume.push_back(static_cast<int>(m_newBar.vol));
//        m_vecBars.push_back(m_newBar);
//        memset(&m_newBar, 0, sizeof(m_newBar));
//        qDebug() << "newbar add.";
//    }

    emit OnDataUpdated();

}
void TrDataManager::OnBar(WTSBarStruct bar)
{
    m_vecOpen.push_back(bar.open);
    m_vecHigh.push_back(bar.high);
    m_vecLow.push_back(bar.low);
    m_vecClose.push_back(bar.close);
    m_vecVolume.push_back(static_cast<int>(bar.vol));
    m_vecBars.push_back(bar);
}
unsigned long long TrDataManager::size()
{
    return m_vecBars.size();
}

double TrDataManager::highPrice()
{
    return *std::max_element(m_vecHigh.begin(), m_vecHigh.end());
}
double TrDataManager::lowPrice()
{
    return *std::min_element(m_vecLow.begin(), m_vecLow.end());
}
double TrDataManager::highPrice(int count, int deviation)
{
    //if (count >= m_vecHigh.size() || (count + deviation) >= m_vecHigh.size()) return highPrice();
    return *std::max_element(m_vecHigh.begin()+deviation, m_vecHigh.begin()+deviation+count);
}
double TrDataManager::lowPrice(int count, int deviation)
{
    //if (count >= m_vecLow.size() || (count + deviation) >= m_vecLow.size()) return lowPrice();
    return *std::min_element(m_vecLow.begin()+deviation, m_vecLow.begin()+deviation+count);
}
double TrDataManager::highPrice(double drift)
{
    auto maxPrice = highPrice() + drift;
    return ceil(maxPrice/10)*10;
}
double TrDataManager::lowPrice(double drift)
{
    auto minPrice = lowPrice() - drift;
    return floor(minPrice/10)*10;
}
WTSBarStruct TrDataManager::getBar(int i)
{
    return m_vecBars.at(static_cast<uint>(i));
}
std::vector<WTSBarStruct> TrDataManager::getBars()
{
    return m_vecBars;
}
void TrDataManager::OnQuote(char* json, char* period)
{

    if(QString::fromLatin1(period).contains(m_strCode))
    {
        QJsonParseError json_error;
        QJsonDocument json_doc = QJsonDocument::fromJson(json, &json_error);
        if(json_doc.isNull() || json_doc.isEmpty() || json_error.error != QJsonParseError::NoError)return;
        QString dateRule = QString(period).right(1) == "0" ? "yyyy-MM-dd" : "yyyy-MM-dd hh:mm:ss";

        if(json_doc.isArray()){

            QJsonArray arr=json_doc.array();
            for(int i = 0; i < arr.size(); i++)
            {
                QJsonObject obj = arr.at(i).toObject();

                double open = obj.value("o").toString().toDouble();
                double high = obj.value("h").toString().toDouble();
                double low = obj.value("l").toString().toDouble();
                double close = obj.value("c").toString().toDouble();
                int volume = obj.value("v").toString().toInt();

                QString qstDate = obj.value("d").toString();

                uint uDate = QDateTime::fromString(qstDate, dateRule).toTime_t();

                WTSBarStruct bar;
                bar.date    =   uDate;
                bar.time    =   uDate;
                bar.open = open;
                bar.high = high;
                bar.low = low;
                bar.close = close;
                bar.vol = volume;
                m_uLastUpdate = uDate;
                OnBar(bar);

            }
        }
        m_dLastPrice = m_vecClose.back();
    }
}
double TrDataManager::lastPrice()
{
    return m_dLastPrice;
}
uint TrDataManager::lastUpdateTime()
{
    return m_uLastUpdate;
}
